// 来自清华
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 2e5 + 5;

set<pair<int, int>> G[MAXN];
int cnt[MAXN];
bool vis[MAXN];
int n, m;

void dfs(int v, int l) {
  if (v == n) {
    ++cnt[l];
    return;
  }
  vis[v] = 1;
  for (auto [x, w] : G[v]) {
    if (vis[x])
      continue;
    dfs(x, l + w);
  }
  vis[v] = 0;
}

int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; ++i) {
    int u, v;
    scanf("%d%d", &u, &v);
    G[u].insert({v, 1});
    G[v].insert({u, 1});
  }
  // step1: 删除所有deg=1
  queue<int> q;
  for (int i = 2; i <= n - 1; ++i) {
    if (G[i].size() == 1)
      q.push(i);
  }
  while (!q.empty()) {
    int v = q.front();
    q.pop();
    // 删除v 这个点
    int to = G[v].begin()->first;
    G[to].erase({v, 1});
    if (to != 1 && to != n && G[to].size() == 1)
      q.push(to);
  }
  // step2: 合并deg=2的点
  for (int i = 2; i <= n - 1; ++i) {
    if (G[i].size() == 2) {
      auto [u, w1] = *G[i].begin();
      auto [v, w2] = *next(G[i].begin());
      // 在u和v中删除i
      G[u].erase(G[u].find({i, w1}));
      G[v].erase(G[v].find({i, w2}));
      // 添加u到v的边
      G[u].insert({v, w1 + w2});
      G[v].insert({u, w1 + w2});
    }
  }
  dfs(1, 0);
  for (int i = 1; i <= n - 1; ++i)
    printf("%d%c", cnt[i], " \n"[i == n]);
  return 0;
}